package com.lc.rabbit.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @description: some desc
 * @author: LChuang
 * @date: 2023/10/24 8:58
 */
@Configuration
public class DirectRabbitConfig {

    /**
     * 工作模式：
     *      一个消息经过交换机进入一个队列
     */

    @Bean
    public Queue rabbitmq01Queue() {
        /*
         * 1、name:    队列名称
         * 2、durable: 是否持久化
         * 3、exclusive: 是否独享、排外的。如果设置为true，定义为排他队列。则只有创建者可以使用此队列。也就是private私有的。
         * 4、autoDelete: 是否自动删除。也就是临时队列。当最后一个消费者断开连接后，会自动删除。
         */
        return new Queue(RabbitMqConstant.WORK_TOPIC, true, false, false);
    }

    /**
     * 路由交换机
     */
    @Bean
    public DirectExchange directExchange() {
        //Direct交换机
        return new DirectExchange(RabbitMqConstant.WORK_DIRECT_EXCHANGE, true, false);
    }

    @Bean
    public Binding bind1Direct() {
        //绑定交换机和队列，并设置匹配键
        return BindingBuilder
                .bind(rabbitmq01Queue())//绑定队列
                .to(directExchange())//到交换机
                .with(RabbitMqConstant.WORK_DIRECT_ROUTING);//并设置匹配键
    }

// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    /**
     * 广播/订阅模式：
     *      一个消息经过相同的交换机进入多个队列
     */
    @Bean
    public Queue publish01Queue() {
        return new Queue(RabbitMqConstant.PUBLISH_01_TOPIC, true, false, false);
    }
    @Bean
    public Queue publish02Queue() {
        return new Queue(RabbitMqConstant.PUBLISH_02_TOPIC, true, false, false);
    }

    /**
     * 广播交换机
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(RabbitMqConstant.FANOUT_EXCHANGE, true, false);
    }

    /**
     * 广播交换机与广播队列绑定
     */
    @Bean
    public Binding queue01FanoutBinding() {
        return BindingBuilder.bind(publish01Queue()).to(fanoutExchange());
    }

    @Bean
    public Binding queue02FanoutBinding() {
        return BindingBuilder.bind(publish02Queue()).to(fanoutExchange());
    }

// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 生产者消息->交换机--(两种路由关系)-->延时队列1，延时队列2--(死信路由关系)-->死信交换机->死信队列
     */

    @Bean
    public DirectExchange delayedExchange() {
        // 延迟消息交换机
        return new DirectExchange(RabbitMqConstant.DELAYED_EXCHANGE, true, false);
    }

    @Bean
    public DirectExchange deadExchange() {
        // 死信交换机
        return new DirectExchange(RabbitMqConstant.DEAD_EXCHANGE, true, false);
    }

    @Bean
    public Queue delayed01Queue() {
        /*延时消息队列01*/
        Map<String, Object> params = new HashMap<>(3);
        //设置死信交换机
        params.put("x-dead-letter-exchange", RabbitMqConstant.DEAD_EXCHANGE);
        //设置死信RoutingKey
        params.put("x-dead-letter-routing-key", RabbitMqConstant.DEAD_ROUTING);
        //设置 TTL 3s，3s后由死信队列消费
        params.put("x-message-ttl", 3000);
        return  QueueBuilder.durable(RabbitMqConstant.DELAYED01_TOPIC).withArguments(params).build();
    }

    @Bean
    public Queue delayed02Queue() {
        /*延时消息队列02*/
        Map<String, Object> params = new HashMap<>(3);
        params.put("x-dead-letter-exchange", RabbitMqConstant.DEAD_EXCHANGE);
        params.put("x-dead-letter-routing-key", RabbitMqConstant.DEAD_ROUTING);
        params.put("x-message-ttl", 5000);
        return  QueueBuilder.durable(RabbitMqConstant.DELAYED02_TOPIC).withArguments(params).build();
    }

    @Bean
    public Queue delayed03Queue() {
        /*延时消息队列03*/
        Map<String, Object> params = new HashMap<>(3);
        params.put("x-dead-letter-exchange", RabbitMqConstant.DEAD_EXCHANGE);
        params.put("x-dead-letter-routing-key", RabbitMqConstant.DEAD_ROUTING);
        // 此队列不设置TTL
        return  QueueBuilder.durable(RabbitMqConstant.DELAYED03_TOPIC).withArguments(params).build();
    }

    @Bean
    public Queue deadQueue() {
        /*死信队列*/
        return  QueueBuilder.durable(RabbitMqConstant.DEAD_TOPIC).build();
    }

    /*绑定队列，交换机，路由键关系*/
    @Bean
    public Binding delayed01DirectBinding() {
        return BindingBuilder
                .bind(delayed01Queue())
                .to(delayedExchange())
                .with(RabbitMqConstant.DELAYED01_ROUTING);
    }

    @Bean
    public Binding delayed02DirectBinding() {
        return BindingBuilder
                .bind(delayed02Queue())
                .to(delayedExchange())
                .with(RabbitMqConstant.DELAYED02_ROUTING);
    }

    @Bean
    public Binding delayed03DirectBinding() {
        return BindingBuilder
                .bind(delayed03Queue())
                .to(delayedExchange())
                .with(RabbitMqConstant.DELAYED03_ROUTING);
    }

    @Bean
    public Binding deadDirectBinding() {
        return BindingBuilder
                .bind(deadQueue())
                .to(deadExchange())
                .with(RabbitMqConstant.DEAD_ROUTING);
    }


// ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 通配符模式：
     *      根据路由键进行匹配转发
     */
    @Bean
    public Queue wildcard01Queue() {
        return  QueueBuilder.durable(RabbitMqConstant.WILDCARD01_TOPIC).build();
    }
    @Bean
    public Queue wildcard02Queue() {
        return  QueueBuilder.durable(RabbitMqConstant.WILDCARD02_TOPIC).build();
    }
    @Bean
    public Queue wildcard03Queue() {
        return  QueueBuilder.durable(RabbitMqConstant.WILDCARD03_TOPIC).build();
    }

    /**
     * 通配符交换机
     */
    @Bean
    public TopicExchange wildcardExchange() {
        return new TopicExchange(RabbitMqConstant.WILDCARD_EXCHANGE, true, false);
    }

    @Bean
    public Binding wildcard01Binding() {
        return BindingBuilder
                .bind(wildcard01Queue())
                .to(wildcardExchange())
                .with(RabbitMqConstant.WILDCARD01_ROUTING);
    }

    @Bean
    public Binding wildcard02Binding() {
        return BindingBuilder
                .bind(wildcard02Queue())
                .to(wildcardExchange())
                .with(RabbitMqConstant.WILDCARD02_ROUTING);
    }

    @Bean
    public Binding wildcard03Binding() {
        return BindingBuilder
                .bind(wildcard03Queue())
                .to(wildcardExchange())
                .with(RabbitMqConstant.WILDCARD03_ROUTING);
    }
}
